import NetInfo from "@react-native-community/netinfo";
import moment from "moment";
import XLog from "../libs/XLog";
import CommunicationManager from "./CommunicationManager";
import DataCenter from "./DataCenter";
import { MQTT_CONNECT_STATUS, ProductID, RegisterType } from "./LogicConstant";
import { DeviceEventEmitter } from "react-native";
import MQTTServer from "../libs/MQTTServer";
import CommandManager from "./CommandManager";
import MQTTClient from "../libs/MQTTClient";
import { formatterMqttConnectState } from "./Utils";
import SerialPorts from "../libs/SerialPortClient";
import { RS_Device_Type } from "../libs/SerialCommon";
import SerialPortManager from "./SerialPortManager";

const ErrorConst = {
    ERROR_MQTTSERVER : 1,
    ERROR_LOCALMQTT : 2,
    ERROR_REMOTEMQTT: 3,
    ERROR_LOOPCONTROLLER: 4,
    ERROR_SMARTMETER: 5,
}

export default class ErrorRecoveryManager {
    static  xErrorMap = {1:0, 2: 0, 3: 0, 4:0, 5: 0};
    static  errorRecoveryTimer = null;
    static  ERROR_CHECK_LIMIT = 3;

    static  installErrorRecoveryManager() {
        this.errorRecoveryTimer = setInterval(async()=>{
            try{
                let netInfoState = await NetInfo.fetch();
                if(netInfoState.isConnected) {
                    let checkKeys = [];
                    for(let error_key of Object.keys(this.xErrorMap)) {
                        if(this.ERROR_CHECK_LIMIT <= this.xErrorMap[error_key]) {
                            if(this.recovery(error_key)) {
                                this.xErrorMap[error_key] = 0;
                            }
                        } else {
                            checkKeys.push(error_key);
                        }
                    }
                    for(let check_item of checkKeys) {
                        let hasError = await this.errorCheck(check_item);
                        if(hasError) {
                            this.xErrorMap[check_item] += 1;
                        } else {
                            this.xErrorMap[check_item] = 0;
                        }
                    }
                }
                
            }catch(error) {
                XLog.e("recovery exception:",error?.message)
            }
        }, 1000 * 60);
    }

    static uninstallErrorRecoveryManager() {
        if(this.errorRecoveryTimer) {
            clearInterval(this.errorRecoveryTimer);
            this.errorRecoveryTimer = null;
        }
    }

    static async recovery(type) {
        try{
            if(type == ErrorConst.ERROR_MQTTSERVER) {
                //我是主控并且有网
                if(DataCenter.isMaster) {
                    XLog.e("recovery broker, i am master");
                    await CommunicationManager.destroyMqttServer();
                    await CommunicationManager.createMqttServer();
                    return true;
                } else {
                    XLog.e("recovery broker, i am not master");
                    return true;
                }
            } else if(type == ErrorConst.ERROR_LOCALMQTT) {
                if(DataCenter.masterIp && CommunicationManager.localMqttConnectStatus != MQTT_CONNECT_STATUS.CONNECT_SUCCESS){
                    await CommunicationManager.destroyLocalMqttClient();
                    let clients = await MQTTClient.getMqttClients("local");
                    for(let clientItem of clients||[]) {
                        XLog.e("recovery local mqtt, destroy native client:", clientItem);
                        await MQTTClient.destroyMqttClientByRef(clientItem);
                    }
                    await CommunicationManager.createLocalMqttClient();
                    CommandManager.installLocalMqttCommand();
                    XLog.e("recovery local mqtt, create");
                    return true;
                } else if(CommunicationManager.localMqttConnectStatus == MQTT_CONNECT_STATUS.CONNECT_SUCCESS) {
                    XLog.e("recovery local mqtt, has connected");
                    return true;
                } else {
                    XLog.e("recovery local mqtt, failed:", DataCenter.masterIp);
                    return false;
                }
            } else if(type == ErrorConst.ERROR_REMOTEMQTT) {
                if(DataCenter.serverIp && CommunicationManager.remoteMqttConnectStatus != MQTT_CONNECT_STATUS.CONNECT_SUCCESS){
                    await CommunicationManager.destroyRemoteMqttClient();
                    let clients = await MQTTClient.getMqttClients("remote");
                    for(let clientItem of clients||[]) {
                        XLog.e("recovery remote mqtt, destroy native client:", clientItem);
                        await MQTTClient.destroyMqttClientByRef(clientItem);
                    }
                    await CommunicationManager.createRemoteMqttClient();
                    CommandManager.installRemoteMqttCommand();
                    XLog.e("recovery remote mqtt, create");
                    return true;
                } else if(CommunicationManager.remoteMqttConnectStatus == MQTT_CONNECT_STATUS.CONNECT_SUCCESS) {
                    XLog.e("recovery remote mqtt, has connected");
                    return true;
                } else {
                    XLog.e("recovery remote mqtt, failed:", DataCenter.serverIp);
                    return false;
                }
            } else if(type == ErrorConst.ERROR_LOOPCONTROLLER) {
                if(DataCenter.registerStatus == RegisterType.REGISTER_SUCCESS) {
                    await SerialPortManager.removeAllDevice(ProductID.LOOP);
                    await SerialPortManager.createDevice(ProductID.LOOP, DataCenter.loopControllerList);
                    return true;
                } else {
                    return true;
                }
            } else if(type == ErrorConst.ERROR_SMARTMETER) {
                if(DataCenter.registerStatus == RegisterType.REGISTER_SUCCESS) {
                    await SerialPortManager.removeAllDevice(ProductID.SMART);
                    await SerialPortManager.createDevice(ProductID.SMART, DataCenter.smartMeterList);
                    return true;
                } else {
                    return true;
                }
            }
        }catch(error) {
            XLog.e("recovery exception:", type, error?.message);
            return false;
        }
    }

    static async errorCheck(type) {
        try{
            if(type == ErrorConst.ERROR_MQTTSERVER) {
                //我是主控并且有网
                if(DataCenter.isMaster) {
                    let isRunning = await MQTTServer.isMQTTServiceRunning();
                    XLog.e("error check broker isRunning:", isRunning);
                    return !isRunning;
                } else {
                    return false;
                }
            } else if(type == ErrorConst.ERROR_LOCALMQTT) {
                if(DataCenter.masterIp && CommunicationManager.localMqttConnectStatus != MQTT_CONNECT_STATUS.CONNECT_SUCCESS){
                    XLog.e("error check local mqttt :", DataCenter.masterIp, formatterMqttConnectState(CommunicationManager.localMqttConnectStatus));
                    return true;
                } else {
                    return false;
                }
            } else if(type == ErrorConst.ERROR_REMOTEMQTT) {
                if(DataCenter.serverIp && CommunicationManager.remoteMqttConnectStatus != MQTT_CONNECT_STATUS.CONNECT_SUCCESS){
                    XLog.e("error check remote mqttt :", DataCenter.serverIp, formatterMqttConnectState(CommunicationManager.remoteMqttConnectStatus));
                    return true;
                } else {
                    return false;
                }
            } else if(type == ErrorConst.ERROR_LOOPCONTROLLER) {
                let isLoopControllerRunning = await SerialPorts.isSerialPortRunning(""+RS_Device_Type.LOOP_4WAY);//key
                if(!isLoopControllerRunning && DataCenter.registerStatus == RegisterType.REGISTER_SUCCESS) {
                    XLog.e("error check loopController not running");
                    return true;
                }
                return false;
            } else if(type == ErrorConst.ERROR_SMARTMETER) {
                let isSmartMeterRunning = await SerialPorts.isSerialPortRunning(""+RS_Device_Type.METER);//key
                if(!isSmartMeterRunning && DataCenter.registerStatus == RegisterType.REGISTER_SUCCESS) {
                    XLog.e("error check smartMeter not running");
                    return true;
                }
                return false;
            }
        }catch(error) {
            XLog.e("errorCheck exception:", type, error?.message);
            return false;
        }
    }
}